package com.study.config;

import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.Assert;

import com.study.entity.db1.SpringScheduledCronPO;
import com.study.mapper.db1.SpringScheduledCronMapper;
import com.study.service.ScheduledOfTask;

/**
 * 定时任务读取数据库配置
 * 
 * @author chenk
 *
 */
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {

	@Autowired
	private ApplicationContext applicationContext;

	@Autowired
	private SpringScheduledCronMapper scheduledCronMapper;

	@Override
	public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
		List<SpringScheduledCronPO> scheduledCronList = scheduledCronMapper.findAll();
		for (SpringScheduledCronPO scheduledCron : scheduledCronList) {
			Class<?> clazz;
			Object task;
			try {
				clazz = Class.forName(scheduledCron.getCronKey());
				task = applicationContext.getBean(clazz);
			} catch (ClassNotFoundException e) {
				throw new IllegalArgumentException("spring_scheduled_cron表数据" + scheduledCron.getCronKey() + "有误", e);
			} catch (BeansException e) {
				throw new IllegalArgumentException(scheduledCron.getCronKey() + "未纳入到spring管理", e);
			}
			Assert.isAssignable(ScheduledOfTask.class, task.getClass(), "定时任务类必须实现ScheduledOfTask接口");
			// 可通过改变数据库数据进而实现动态改变执行周期
			taskRegistrar.addTriggerTask(((Runnable) task), triggerContext -> {
				String cronExpression = scheduledCronMapper.findByCronKey(scheduledCron.getCronKey())
						.getCronExpression();
				return new CronTrigger(cronExpression).nextExecutionTime(triggerContext);
			});

		}
	}

	@Bean
	public Executor taskExecutor() {
		return Executors.newScheduledThreadPool(10);
	}

}
